package divinity.animation.tweener
{
	import divinity.animation.tweener.transitions.Transitions;
	import divinity.utils.log.Log;
	import fl.motion.BezierSegment;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	
	/**
	 * ...
	 * @author Filip Prebeg
	 */
	public class Tweener extends EventDispatcher
	{
		private static var _tweenNum:int = 0;
		private var _log:Log;
		private var _startTime:int;
		private var _clip:Sprite;
		private var _elapsed:int;
		private var _currentTime:int = 0;
		private var _totalTime:int = 1;
	
		private var _int:Number;
		private var _point:Array;
		private var _bz:BezierSegment;
		private var _factorial:Array = [];
		private var _props:Object = {};
		
		public function Tweener(clip:*, props:Object)
		{
			
			super();
			_props = props;
			_tweenNum++;
			
			//	Create log
			_log = new Log("Tweener" + _tweenNum);
			
			//	 Make start time
			_startTime = new Date().getTime();
			_clip = clip;
			_totalTime = props.time
			
			//	Create bezier
			_point = Transitions[props.transition]
			_bz = new BezierSegment(_point[0], _point[1], _point[2], _point[3]);
			
			//	Set defaults
			setDefaults()
			
			//_int = setInterval(cycle, 10);
			_clip.addEventListener(Event.ENTER_FRAME, cycle);
			_log.addLog(this, "Tweener started for clip " + clip);
		}
		
		private function parse(props:Object)
		{
			var obj:Object = {};
			for (var prop in props)
			{
				obj[prop] = props[prop];
				trace(prop);
			}
			return obj;
		}
		
		private function setDefaults()
		{
			
			
			if (_props.x != null)
			{
				_props._startX = _clip.x;
				_props._distX = _props.x - _clip.x;
				_props._facX = _props._distX / _props.time;
			}
			
			if (_props.y != null)
			{
				_props._startY = _clip.y;
				_props._distY = _props.y - _clip.y;
				_props._facY = _props.distY / _props.time;
			}
			
			
			if (_props.scaleX != null)
			{
				_props._startScaleX = _clip.scaleX;
				_props._distScaleX = _props.scaleX - _clip.scaleX;
				_props._facScaleX = _props.distScaleX / _props.time;
			}
			if (_props.scaleY != null)
			{
				_props._startScaleY = _clip.scaleY;
				_props._distScaleY = _props.scaleY - _clip.scaleY;
				_props._facScaleY = _props.distScaleY / _props.time;
			}
		
		}
		
		private function cycle(e:Event = null)
		{
			
			_elapsed = new Date().getTime();
			_elapsed -= _startTime;
			if (_props.smooth)
			{
				_factorial.push(_elapsed);				
				_currentTime += getAverage()
			}
			else
			{
				_currentTime += _elapsed;
			}
			//_currentTime+=10;
			if (_currentTime > _totalTime)
			{
				_currentTime = _totalTime;
				transform();
				destroyMe();
			}
			else
			{
				transform();
			}
			_startTime = new Date().getTime();
		}
		
		private function transform()
		{
			var _norm:Number = _currentTime / (_totalTime);
			var _fac:Number = (_bz.getValue(_norm).y) / 100
			if (_props.x != null)
			{
				var xx = _props._startX + (_props._distX * _fac);
				_clip.x = xx;
			}
			if (_props.y != null)
			{
				var yy = _props._startY + (_props._distY * _fac);
				_clip.y = yy;
			}
			
			if (_props.scaleX != null)
			{
				var sx = _props._startScaleX + (_props._distScaleX * _fac);
				_clip.scaleX = sx;
			}
			if (_props.scaleY != null)
			{
				var sy = _props._startScaleY + (_props._distScaleY * _fac);
				_clip.scaleY = sy;
			}
			if (_props.onTween != null)
			{
				_props.onTween(this);
			}
		}
		
		public function destroyMe()
		{
			trace("destroying");
			_clip.removeEventListener(Event.ENTER_FRAME, cycle);
			_log.addLog(this, "Tweener complete for clip " + _clip);
			//trace(Log.list);
			//clearInterval(_int);
		}
		
		private function getAverage()
		{
			var b:Number = 0;
			for (var n = 0; n < _factorial.length; n++)
			{
				b += _factorial[n];
			}
			b /= _factorial.length;
			return b;
		}
		public function get PROPS():Object
		{
			return _props;
		}
		public function get CLIP():*
		{
			return _clip;
		}
	}

}